package Concurrency2.Chapter01_Base;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Instruction: 定义线程的方式
 * Author：@author MaLi
 */
public class Topic01_CreateThread {
    private static final Logger logger = LoggerFactory.getLogger(Topic01_CreateThread.class);

    /*
        测试: 创建线程实例, 并启动线程
     */
    public static void main(String[] args) {
        //测试方式1: 继承Thread类
        SomeThread someThread = new SomeThread();
        someThread.start();//启动线程

        //测试方式2: 实现Runnable接口
        Thread someRunnable = new Thread(new SomeRunnable());
        someRunnable.start();

        //测试方式3: 匿名内部类, 本质上还是方式2, 仅仅是传参的时候传的是一个匿名类的实例
        Thread someAnonymousRunnable = new Thread(new Runnable() {
            @Override
            public void run() {
                Thread ct = Thread.currentThread();
                logger.info(" 方式3 --> 线程名: {} --> 线程ID: {} -->  线程状态:{} --> 线程权限:{}", ct.getName(), ct.getId(), ct.getState(), ct.getPriority());
            }
        });
        someAnonymousRunnable.start();

        //测试方式4: lambda表达式, 本质上还是方式2, 通过lambda表达式方式创建匿名类的实例
        Thread someLambdaRunnable = new Thread(() -> {
            Thread ct = Thread.currentThread();
            logger.info(" 方式4 --> 线程名: {} --> 线程ID: {} -->  线程状态:{} --> 线程权限:{}", ct.getName(), ct.getId(), ct.getState(), ct.getPriority());
        });
        someLambdaRunnable.start();
    }
}

/*
    方式一, 继承Thread定义线程逻辑 (实际开发不采用)
 */
class SomeThread extends Thread {
    private static final Logger logger = LoggerFactory.getLogger(SomeThread.class);

    @Override
    public void run() {
        //由于是继承的Thread类, 那么直接复用复用父类的方法, 来获取线程Name和Id
        logger.info(" 方式1 --> 线程名: {} --> 线程ID: {} -->  线程状态:{} --> 线程权限:{}", this.getName(), this.getId(), this.getState(), this.getPriority());
    }
}

/*
    方式二: 实现Runnbale接口定义线程任务逻辑
 */
class SomeRunnable implements Runnable {
    private static final Logger logger = LoggerFactory.getLogger(SomeRunnable.class);

    @Override
    public void run() {
        // 获取Thread实例
        Thread ct = Thread.currentThread();
        logger.info(" 方式2 --> 线程名: {} --> 线程ID: {} -->  线程状态:{} --> 线程权限:{}", ct.getName(), ct.getId(), ct.getState(), ct.getPriority());
    }
}

/*
面试题: 在生产中采用哪种方式如何创建线程?(注意是创建线程而不是执行线程任务)
答案: 实现Runnable接口
理由:
    小马哥的答案: 我们自己手动创建不了线程, 线程是操作系统创建的, 我们只能定义线程任务, 也就是线程执行的代码逻辑, 而Runnable就是对这个逻辑的规范协议.
    Thread代表的是线程, Runnable代表的是线程任务的规范, Runnable实现代表的是线程任务
    最佳实践是, 创建线程任务, 提交给线程池去执行该任务.

    此外, 网络上还有如下答案
    1, Java是单继承的, 也就是只能继承一个父类, 如果使用继承Thread的方式, 那么该子类就不能继承其它类了; (不绝对, A-->B-->C-->Thread照样可以实现多继承)
    2, Runnable的本质就是定义一个线程任务在run()方法中, 最佳实践是将定义好的任务, 提交给线程池去执行, 而不是通过Thread去执行.(算是一个理由)
 */
